#coding:utf-8

import os
import types
import traceback

from sqlite3 import dbapi2 as sqlite

from sqlalchemy import create_engine
from sqlalchemy import Table, Column, MetaData, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship, backref
from sqlalchemy.dialects.sqlite import BOOLEAN, CHAR, INTEGER, TEXT, VARCHAR
from sqlalchemy.orm.interfaces import SessionExtension

import error
import utils

class SessionLoger(SessionExtension):
    def before_commit(self, session):
        print 'before', dir(session)
        
    def after_commit(self, session):
        print 'after', session
        
    def before_flush(self, session, flush_context, instances):
        pass
    
    def after_flush(self, session, flush_context):
        pass
    
Session = sessionmaker(extension=SessionLoger())
_Base = declarative_base()

def _format_dict(dict_object):
    for k in dict_object:
        dict_object[k] = str(dict_object[k])
    return str(dict_object)

class Message(_Base):
    __tablename__ = 'message'
    id = Column(INTEGER, primary_key=True)
    result_id = Column(INTEGER, ForeignKey('result.id'))
    order = Column(INTEGER)
    msg = Column(VARCHAR)
    env = Column(VARCHAR)
    def __init__(self, order, msg, env):
        self.order = order
        self.msg = msg
        self.env = _format_dict(env)
        
    def __repr__(self):
        return "<Message result_id=%s, order=%s, msg=%s>"%(self.result_id, self.order, self.msg)

class Result(_Base):
    __tablename__ = 'result'
    id = Column(INTEGER, primary_key=True)
    case_id = Column(INTEGER, ForeignKey('testcase.id'))
    result = Column(BOOLEAN)
    time_start = Column(VARCHAR)
    time_stop = Column(VARCHAR)
    args = Column(VARCHAR)
    messages = relationship(Message, backref=__tablename__, cascade="all, delete, delete-orphan")
    def __init__(self, result, time_start, time_stop, args):
        self.result = result
        self.time_start = time_start
        self.time_stop = time_stop
        self.args = _format_dict(args)
        
    def __repr__(self):
        return "<Result case_id=%s, result=%s, time_start=%s, time_stop" \
                "=%s>"%(self.case_id, self.result, self.time_start, self.time_stop)
        
class TestCase(_Base):
    __tablename__ = 'testcase'
    id = Column(INTEGER, primary_key=True)
    name = Column(VARCHAR)
    path = Column(VARCHAR)
    description = Column(VARCHAR)
    results = relationship(Result, backref=__tablename__, cascade="all, delete, delete-orphan")
    def __init__(self, name, path, description=''):
        self.name = name
        self.path = path
        self.description = description
    
    def __repr__(self):
        return "<TestCase name=%s, path=%s, desc=%s>"%(self.name, self.path, self.description)

class SystemError(_Base):
    __tablename__ = 'system_error'
    id = Column(INTEGER, primary_key=True)
    when = Column(VARCHAR)
    message = Column(VARCHAR)
    def __init__(self):
        self.when = utils.now()
        self.message = ''.join(traceback.format_exception(*error.last_error()))

def get_engine(datapath, overwrite=False):
    if os.path.isfile(datapath) and overwrite:
        os.remove(datapath)
    engine = create_engine('sqlite+pysqlite:///%s'%datapath, echo=False, module=sqlite)
    _Base.metadata.create_all(engine)
    return engine

